package com.oschina.sequence;

import com.alibaba.fastjson.JSON;
import com.mchange.v2.c3p0.ComboPooledDataSource;
import com.oschina.sequence.exception.SequenceException;

import java.sql.Connection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by limu on 16/6/28.
 */
public class DbPoolManger {
    /**
     * 数据库连接池map
     */
    private static Map<Integer, ComboPooledDataSource> dataSourceMap = new HashMap<>();

    /**
     * 获取连接
     *
     * @param dbIndex dbIndex
     * @return
     * @throws SequenceException
     */
    public static Connection getConnection(int dbIndex) throws SequenceException {
        try {
            return dataSourceMap.get(dbIndex).getConnection();
        } catch (Throwable e) {
            throw new SequenceException("getConnection error", e);
        }
    }

    /**
     * 初始化线程池
     *
     * @param databaseConfigs databaseConfigs
     * @return
     * @throws Exception
     */
    public static void init(List<DatabaseConfig> databaseConfigs) throws SequenceException {
        int count = 0;
        for (DatabaseConfig databaseConfig : databaseConfigs) {
            ComboPooledDataSource dataSource = new ComboPooledDataSource();

            try {
                dataSource.setDriverClass("com.mysql.jdbc.Driver");
                dataSource.setJdbcUrl(databaseConfig.getJdbcUrl());
                dataSource.setUser(databaseConfig.getUserName());
                dataSource.setPassword(databaseConfig.getPassword());

                //初始化连接池中的连接数，取值应在minPoolSize与maxPoolSize之间，默认为3
                dataSource.setInitialPoolSize(3);

                //连接池中保留的最小连接数，默认为：3
                dataSource.setMinPoolSize(3);

                //连接池中保留的最大连接数。默认值: 15
                dataSource.setMaxPoolSize(15);

                //最大空闲时间，600秒内未使用则连接被丢弃。若为0则永不丢弃。默认值: 0
                dataSource.setMaxIdleTime(600);

                //当连接池连接耗尽时，客户端调用getConnection()后等待获取新连接的时间，超时后将抛出SQLException，如设为0则无限期等待。单位毫秒
                dataSource.setCheckoutTimeout(500);

                //当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。默认值: 3
                dataSource.setAcquireIncrement(2);

                //定义在从数据库获取新连接失败后重复尝试的次数。默认值: 30 ；小于等于0表示无限次
                dataSource.setAcquireRetryAttempts(30);

                //重新尝试的时间间隔，默认为：1000毫秒
                dataSource.setAcquireRetryDelay(1000);

                //连接池中的空闲连接时，将使用查询语句进行测试
                dataSource.setPreferredTestQuery("select name from sequence0");

                //每1小时检查所有连接池中的空闲连接。默认值: 0，不检查
                dataSource.setIdleConnectionTestPeriod(3600);

                //c3p0全局的PreparedStatements缓存的大小。如果maxStatements与maxStatementsPerConnection均为0，则缓存不生效，只要有一个不为0，
                // 则语句的缓存就能生效。默认值: 0
                dataSource.setMaxStatements(100);
            } catch (Throwable e) {
                throw new SequenceException("db pool init error, databaseConfigs=" + JSON.toJSONString(databaseConfigs), e);
            }

            dataSourceMap.put(count, dataSource);
            count++;
        }
    }

    /**
     * 销毁连接池
     *
     * @throws SequenceException
     */
    public static void destroy() throws SequenceException {
        try {
            for (Map.Entry<Integer, ComboPooledDataSource> entry : dataSourceMap.entrySet()) {
                ComboPooledDataSource dataSource = entry.getValue();
                dataSource.close();
            }
        } catch (Throwable e) {
            throw new SequenceException("dataSource destroy error", e);
        }
    }


}
